package __queue

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

/**
队列的链表实现
*/

type QNode struct {
	data int
	next *QNode
}

type LinkQueue struct {
	front *QNode // 头指针，头结点的指针，data可以用来表示链表长度
	rear  *QNode // 尾指针
}

func NewLinkQueue() *LinkQueue {
	front := &QNode{}
	rear := &QNode{}
	return &LinkQueue{front: front, rear: rear}
}

func (l *LinkQueue) EnQueue(e int) int {
	if l.QueueLength() >= maxSize {
		return -1
	}
	n := &QNode{data: e}
	if l.QueueEmpty() {
		l.front.next = n
	}
	l.front.data++
	l.rear.next = n
	l.rear = n
	return 0
}

func (l *LinkQueue) GetHead() int {
	if l.QueueEmpty() {
		return -1
	}
	return l.front.next.data
}

func (l *LinkQueue) DeQueue() (int, error) {
	if l.QueueEmpty() {
		return -1, errors.New("queue is empty")
	}
	r := l.front.next.data
	l.front.next = l.front.next.next
	l.front.data--
	return r, nil
}

func (l *LinkQueue) QueueLength() int {
	return l.front.data
}

func (l *LinkQueue) QueueEmpty() bool {
	return l.QueueLength() == 0
}

func (l *LinkQueue) ClearQueue() {
	l.front.data = 0
	l.front.next = nil
	l.rear.next = nil
}

func (l *LinkQueue) String() string {
	sb := strings.Builder{}
	t := l.front.next
	for i := 0; i < l.QueueLength(); i++ {
		sb.WriteString(strconv.Itoa(t.data))
		t = t.next
		if i != l.QueueLength()-1 {
			sb.WriteString("->")
		}
	}
	return fmt.Sprintf("data=%s,length=%d", sb.String(), l.QueueLength())
}
